package ${domain}.frame.validation;

import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import ${domain}.frame.auth.LocalData;
import ${domain}.frame.utils.StringUtil;
import ${domain}.module.wsys.ent.DictItem;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class DictValidator implements ConstraintValidator<Dict, String> {

    private String name;

    @Override
    public void initialize(Dict constraint) {
        name = constraint.name();
    }

    @Override
    public boolean isValid(String o, ConstraintValidatorContext constraintValidatorContext) {
        String fieldName = "";
        // 获取注解的字段名称，用于快速定位排查
        if (constraintValidatorContext instanceof ConstraintValidatorContextImpl) {
            ConstraintValidatorContextImpl validatorContext = (ConstraintValidatorContextImpl) constraintValidatorContext;
            if (validatorContext.getConstraintViolationCreationContexts() != null
                    && validatorContext.getConstraintViolationCreationContexts().size() > 0
                    && validatorContext.getConstraintViolationCreationContexts().get(0).getPath() != null) {
                fieldName = validatorContext.getConstraintViolationCreationContexts().get(0).getPath().asString();
            }
        }

        if (StringUtil.isEmpty(o)) {// 当值为空字符时，认为值有效
            return true;
        } else if (name == null) {// 当字典名称为空时，说明未指定字典，提示错误
            // 禁用默认错误信息，防止错误信息与自定义信息乱串
            constraintValidatorContext.disableDefaultConstraintViolation();
            String message = String.format(Locale.CHINESE, "[ %s ] 未指定字典名称！", fieldName);
            constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
            return false;
        } else {// 加载字典，并验证提交值是否包含在内
            // name 字典名称
            ${domain}.module.wsys.req.DictLoadRequest dictLoadRequest = new ${domain}.module.wsys.req.DictLoadRequest();
            dictLoadRequest.setDictName(name);
            ${domain}.module.wsys.mgr.DictManager dictManager = LocalData.getBean(${domain}.module.wsys.mgr.DictManager.class);
            ${domain}.module.wsys.rsp.DictLoadResponse dictLoadResponse = dictManager.load(dictLoadRequest, LocalData.getSysToken());

            // 如果加载字典出现错误，返回验证错误
            if (dictLoadResponse.hasError()) {
                // 禁用默认错误信息，防止错误信息与自定义信息乱串
                constraintValidatorContext.disableDefaultConstraintViolation();
                String message = String.format(Locale.CHINESE, "[ %s ] 验证字典 [ %s ] 值出现异常-> %s！", fieldName, name, dictLoadResponse.getErrors().get(0).getMessage());
                constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
                return false;
            }

            List<DictItem> dictItems = dictLoadResponse.getDictItems();
            Stream<DictItem> list = dictItems.stream().filter(new Predicate<DictItem>() {
                @Override
                public boolean test(DictItem dictItem) {
                    if (o.equals(dictItem.getKey())) {
                        return true;
                    }
                    return false;
                }
            });
            // 当未找到字典项时，认为值无效，返回验证错误
            if (list.count() == 0) {
                // 禁用默认错误信息，防止错误信息与自定义信息乱串
                constraintValidatorContext.disableDefaultConstraintViolation();
                String message = String.format(Locale.CHINESE, "[ %s ] 指定的字典 [ %s ] 中，未找到字典枚举(%s)！", fieldName, name, o);
                constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
                return false;
            } else {
                return true;
            }
        }
    }
}
